﻿using System;
using System.Diagnostics;
using IInject.Registration.Scanning;
using IInject.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace IInject.Tests
{
	[TestClass]
	public class AssemblyScannerTests
	{
		[TestMethod]
		public void TestDefaultConventions()
		{
			var container = new Container();
			container.Scan(a => a.ScanCallingAssembly());
		}

		[TestMethod]
		public void TestTypeConventions()
		{
			var container = new Container();
			ScanRules.Current.Clear();
			ScanRules.Current.Add(ScanningRule.Inherits<AbstractDependent>());
			container.Scan(a => a.ScanCallingAssembly());

			var test = container.Get<Dependent3>();
			Assert.IsTrue(test != null, "test != null");
		}

		[TestMethod]
		public void TestInterfaceScanConventions()
		{
			var container = new Container();
			ScanRules.Current.Clear();
            ScanRules.Current.Add(ScanningRule.Implements<IDependencyTest>());
			container.Scan(a => a.ScanCallingAssembly());

			var test = container.Get<IDependencyTest>();
			Assert.IsTrue(test is DependencyTest);
		}

		[TestMethod]
		public void TestInterfaceNamingScanConventions()
		{
			var container = new Container();
			ScanRules.Current.Clear();
            ScanRules.Current.Add(ScanningRule.InterfaceNamingDefault());

            container.Set<Dependent, Dependent3>();
			container.Scan(a => a.ScanCallingAssembly());

			var test1 = container.Get<IDependencyTest>();
			var test2 = container.Get<IInjectedProperty>();

            Assert.IsNotNull(test1);
            Assert.IsNotNull(test2);
            Assert.IsNotNull(test1 is DependencyTest);
            Assert.IsNotNull(test2 is InjectedProperty);
            Assert.IsNotNull(test1.Child is Dependent3);
            Assert.IsNotNull(test2.Dependent is Dependent3);
		}

		[TestMethod]
		public void TestUsingConventionScanConventions()
		{
			var container = new Container();

			container.Scan(a =>
			{
                a.Using(ScanningRule.InterfaceNamingDefault());
				a.ScanCallingAssembly();
			});

			var test = container.Get<IDependencyTest>();
			Assert.IsNotNull(test);
		}

        [TestMethod]
        public void TestAddConventionsScanConventions()
        {
            var container = new Container();

            container.Scan(a =>
            {
                a.Add(ScanningRule.InterfaceNamingDefault());
                a.Add(ScanningRule.PublicClass());
                a.ScanCallingAssembly();
			});

            var test = container.Get<IDependencyTest>();
            Assert.IsNotNull(test);
        }

		/// <summary>
		///A test for ResolveAll
		///</summary>
		[TestMethod]
		public void AbstractClassDoesntGetRegisteredUsingInterfaceRuleTest()
		{
			var container = new Container();
			container.Scan(a =>
			{
				a.Using(ScanningRule.InterfaceNamingDefault());
				a.ScanCallingAssembly();
			});

			try
			{
				var test = container.Get<IAbstractDependent>();
			}
			catch (Exception)
			{
				return;
			}

			Assert.Fail("AbstractClassDoesntGetRegisteredUsingInterfaceRuleTest scanned and registered a abstract class using the InterfaceNamingDefault rule.");
		}
	}
}
